package archforce.atp.x;

import archforce.atp.x.bs.SaveBtnBS;
import archforce.atp.x.ssh.entity.JumpConfig;
import archforce.atp.x.ssh.entity.JumpMappingConfig;
import archforce.atp.x.ssh.entity.PortMappingEntity;
import archforce.atp.x.ssh.jsch.JschDockerService;
import archforce.atp.x.ssh.tool.PersistenceConfigTool;
import archforce.atp.x.ui.frame.component.FacedComponent;
import archforce.atp.x.ui.impl.common.model.JumpMappingModel;
import archforce.atp.x.ui.impl.common.model.PanelDataModel;
import archforce.atp.x.ui.impl.left.IPPortGroupComponent;
import archforce.atp.x.ui.impl.left.IPPortModel;
import archforce.atp.x.ui.impl.left.SelectActionListener;
import archforce.atp.x.ui.impl.right.IPPortMappingItemComponent;
import archforce.atp.x.ui.impl.right.IPPortMappingModel;
import com.jcraft.jsch.Session;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wx
 * @version 1.0
 * @date 2022/4/6 17:36
 */
public class ConnectConfigView {
    private JPanel parentPanel;
    private JPanel zhegaiceng;
    private JPanel bottonPanel;
    private JScrollPane rightScrollPanel;
    private JButton connectBtn;
    private JButton disConnectBtn;
    private JPanel lCustomerPanel;
    private JPanel rightPanel;
    private JButton staticBtn;
    private JButton autoBtn;
    private JPanel rightTopBtnPanel;
    private JPanel rightContentPanel;
    private JPanel rightTopFunBtnPanel;
    private JPanel rightTopLabelPanel;
    private JButton saveBtn;
    private JTabbedPane lTabbedPane;
    private JPanel lRemotePanel;
    private JTextField nameField;
    private JPasswordField passwdField;
    private JButton refreshConfigBtn;
    private JPanel userInfoInputPanel;
    private JTextArea textArea1;
    private JPanel autoMachPanel;
    private JCheckBox remberUserCbtn;

    private FacedComponent<IPPortMappingItemComponent, IPPortMappingModel> staticModelComponent;
    private JPanel autoModelCardPanel;
    private Map<String, FacedComponent> autoModelFacedComponentMap = new HashMap<>();
    private FacedComponent<IPPortMappingItemComponent, IPPortMappingModel> selectedModel = null;

    private FacedComponent<IPPortGroupComponent, List<IPPortModel>> customerJumpConfigPanel;
    private FacedComponent<IPPortGroupComponent, List<IPPortModel>> remoteJumpConfigPanel;
    private static final String STATIC_PANEL_KEY = "static";
    private static final String AUTO_PANEL_KEY = "auto";

    private Session[] sessions= null;

    public ConnectConfigView() {
        PanelDataModel localData = loadData();
        initRightContentPanel(localData.getDefaultMappingConfigData(), localData.getMappingConfigData());

        initLeftTablePanel(localData.getConnectConfigData());

        saveBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                super.mouseReleased(e);
                SaveBtnBS saveBtnBS = new SaveBtnBS();
                saveBtnBS.save(customerJumpConfigPanel,
                        staticModelComponent,
                        autoModelFacedComponentMap,
                        getAutoModelFacedComponentMapKey(),
                        staticModelComponent == selectedModel,
                        nameField.getText(),
                        passwdField.getSelectedText());
            }
        });
        connectBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                List<IPPortModel> jumpConfig = customerJumpConfigPanel.getSelectedData();
                List<IPPortMappingModel> mappingConfig = selectedModel.getData();
                JumpMappingModel jumpMappingModel = new JumpMappingModel(Integer.parseInt(getAutoModelFacedComponentMapKey()), jumpConfig, mappingConfig);
                System.out.println("selected data:" + jumpMappingModel);
                sessions = JschDockerService.connectAndMapping(parseSSHData(jumpMappingModel));
            }
        });
        disConnectBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                try {
                    System.out.println("test load:" + PersistenceConfigTool.loadPanelData());
                    if(sessions != null){
                        Stream.of(sessions).filter(Objects::nonNull).forEach(Session::disconnect);
                    }
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                } catch (ClassNotFoundException classNotFoundException) {
                    classNotFoundException.printStackTrace();
                }
            }
        });
        staticBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                super.mouseReleased(e);
                CardLayout layout = (CardLayout) rightContentPanel.getLayout();
                layout.show(rightContentPanel, STATIC_PANEL_KEY);
                selectedModel = staticModelComponent;
            }
        });
        autoBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                super.mouseReleased(e);
                CardLayout layout = (CardLayout) rightContentPanel.getLayout();
                layout.show(rightContentPanel, AUTO_PANEL_KEY);
                FacedComponent existed = autoModelFacedComponentMap.get(getAutoModelFacedComponentMapKey());
                if(existed == null){
                    existed = FacedComponent.getInstance(IPPortMappingItemComponent.class, localData.getMappingConfigData().get(getAutoModelFacedComponentMapKey()));
                    autoModelFacedComponentMap.putIfAbsent(getAutoModelFacedComponentMapKey(), existed);
                }
                selectedModel = existed;
//                JOptionPane.showMessageDialog(null, "该功能暂未开放！");
            }
        });
    }

    private PanelDataModel loadData(){
        PanelDataModel panelData = null;
        try {
            panelData = PersistenceConfigTool.loadPanelData();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("load data from local:" + panelData);
        return panelData == null?new PanelDataModel():panelData;
    }

    public JPanel getWindowPanel(){
        return parentPanel;
    }

    private void initLeftTablePanel(List<List<IPPortModel>> rowData){
        this.customerJumpConfigPanel = FacedComponent.getInstance(IPPortGroupComponent.class, rowData);
        this.customerJumpConfigPanel.addSelectActionListener(new SelectActionListener(
                new AtomicBoolean(this.selectedModel == this.staticModelComponent),
                this.autoModelCardPanel,
                this.autoModelFacedComponentMap,
                ConnectConfigView::getAutoModelScrollPanel,
                this::getAutoModelFacedComponentMapKey));
        this.lCustomerPanel.add(this.customerJumpConfigPanel);

        this.remoteJumpConfigPanel = FacedComponent.getInstance(IPPortGroupComponent.class);
        this.remoteJumpConfigPanel.addSelectActionListener(new SelectActionListener(
                new AtomicBoolean(this.selectedModel == this.staticModelComponent),
                this.autoModelCardPanel,
                this.autoModelFacedComponentMap,
                ConnectConfigView::getAutoModelScrollPanel,
                this::getAutoModelFacedComponentMapKey));
        this.lRemotePanel.add(remoteJumpConfigPanel);

        FacedComponent<IPPortGroupComponent, List<IPPortModel>> autoMatchPanel = FacedComponent.getInstance(IPPortGroupComponent.class);
        autoMatchPanel.addSelectActionListener(new SelectActionListener(
                new AtomicBoolean(this.selectedModel == this.staticModelComponent),
                this.autoModelCardPanel,
                this.autoModelFacedComponentMap,
                ConnectConfigView::getAutoModelScrollPanel,
                this::getAutoModelFacedComponentMapKey));
        this.autoMachPanel.add(autoMatchPanel);
    }

    private void initRightContentPanel(List<IPPortMappingModel> staticRows, Map<String,List<IPPortMappingModel>> matchRows) {
        //1.链接配置是自定义配置
        this.staticModelComponent = FacedComponent.getInstance(IPPortMappingItemComponent.class, staticRows);
        this.selectedModel = this.staticModelComponent;
        ScrollPane staticModelScrollPanel = new ScrollPane();
        JPanel lPanel = new JPanel();
        ((FlowLayout)lPanel.getLayout()).setAlignment(FlowLayout.LEFT);
        lPanel.add(this.staticModelComponent);
        staticModelScrollPanel.add(lPanel);
        rightContentPanel.add(staticModelScrollPanel, STATIC_PANEL_KEY);

        //需要根据选中的链接配置的数据从matchRows中获取对应的数据
        this.autoModelCardPanel = new JPanel(new CardLayout());
        if(matchRows == null) {
            FacedComponent instance = FacedComponent.getInstance(IPPortMappingItemComponent.class);
            ScrollPane autoModelScrollPanel = getAutoModelScrollPanel(instance);
            this.autoModelCardPanel.add(autoModelScrollPanel, "10");
            this.autoModelFacedComponentMap.putIfAbsent("10", instance);
        }else{
            matchRows.entrySet().forEach(entry->{
                FacedComponent instance = FacedComponent.getInstance(IPPortMappingItemComponent.class, entry.getValue());
                ScrollPane autoModelScrollPanel = getAutoModelScrollPanel(instance);
                this.autoModelCardPanel.add(autoModelScrollPanel, entry.getKey());
                this.autoModelFacedComponentMap.putIfAbsent(entry.getKey(), instance);
            });
        }
        rightContentPanel.add(this.autoModelCardPanel, AUTO_PANEL_KEY);

        CardLayout layout = (CardLayout) rightContentPanel.getLayout();
        layout.show(rightContentPanel, STATIC_PANEL_KEY);
        //2.链接配置是容器平台获取
        //无初始化
        //3.链接配置是自动匹配
        //无初始化
    }

    //根据左侧面板的选中项获取行对应的key
    private String getAutoModelFacedComponentMapKey(){
        String key = null;
        switch (lTabbedPane.getSelectedIndex()){
            case 0:{
                key = getAutoModelFacedComponentMapKey(this.customerJumpConfigPanel.getSelectedID());
                break;
            }
            case 1:{
                key = getAutoModelFacedComponentMapKey(this.remoteJumpConfigPanel.getSelectedID());
                break;
            }
            default:key = getAutoModelFacedComponentMapKey(null);
        }
        return key;
    }

    //根据左侧面板的选中项获取行对应的key
    private String getAutoModelFacedComponentMapKey(String selectedIndex){
        String key = null;
        switch (lTabbedPane.getSelectedIndex()){
            case 0:{
                selectedIndex = (selectedIndex == null ? "0" : selectedIndex);
                key = "1" + selectedIndex;
                break;
            }
            case 1:{
                selectedIndex = (selectedIndex == null ? "0" : selectedIndex);
                key = "2" + selectedIndex;
                break;
            }
            case 2:{
                selectedIndex = (selectedIndex == null ? "0" : selectedIndex);
                key = "3" + selectedIndex;
                break;
            }
            default:key = "10";
        }
        return key;
    }

    public void addAutoModelPanelCard(String selectedIndex){
        FacedComponent instance = FacedComponent.getInstance(IPPortMappingItemComponent.class);
        ScrollPane autoModelScrollPanel = getAutoModelScrollPanel(instance);
        this.autoModelCardPanel.add(autoModelScrollPanel, selectedIndex, Integer.parseInt(selectedIndex));
        this.autoModelFacedComponentMap.putIfAbsent(selectedIndex, instance);//key 应该使用getAutoModelFacedComponentMapKey
    }

    public void removeAutoModelPanelCard(String selectedIndex){
        this.autoModelCardPanel.remove(Integer.parseInt(selectedIndex));
        this.autoModelFacedComponentMap.remove(selectedIndex);//key 应该使用getAutoModelFacedComponentMapKey
    }

    public void showAutoModelPanelCard(String selectedIndex){
        ((CardLayout)this.autoModelCardPanel.getLayout()).show(this.autoModelCardPanel, selectedIndex);
    }

    private List getRightAutoModelData(String selectedIndex){
        return this.autoModelFacedComponentMap.get(selectedIndex).getData();//bug, need finish
    }

    public static ScrollPane getAutoModelScrollPanel(FacedComponent facedComponent){
        ScrollPane autoModelScrollPanel = new ScrollPane();
        JPanel rPanel = new JPanel();
        ((FlowLayout)rPanel.getLayout()).setAlignment(FlowLayout.LEFT);
        rPanel.add(facedComponent);
        autoModelScrollPanel.add(rPanel);
        autoModelScrollPanel.setPreferredSize(new Dimension(600, 640));
        return autoModelScrollPanel;
    }

    //将面板的数据转换为ssh工具类使用的数据模型
    private JumpMappingConfig parseSSHData(JumpMappingModel data){
        List<IPPortModel> jumpModel = data.getJumpConfig();
        List<JumpConfig.ServerEntity> jumpHostList = new ArrayList<>();
        JumpConfig.ServerEntity master = null;
        for (int i = 0; i < jumpModel.size(); i++) {
            if(i == 0) {
                JumpConfig.ServerEntity target = new JumpConfig.ServerEntity(jumpModel.get(i).getIp(), "archforce", "archforce");
                jumpHostList.add(target);
            }
            if(i == 1) {
                JumpConfig.ServerEntity target = new JumpConfig.ServerEntity(jumpModel.get(i).getIp(), "root", "archforce");
                jumpHostList.add(target);
            }
            if(i == 2) {
                JumpConfig.ServerEntity target = new JumpConfig.ServerEntity(jumpModel.get(i).getIp(), "archforce", "archforce");
                master = new JumpConfig.ServerEntity(target.getHostIP(), target.getUser(), target.getPassword());
            }
        }
        JumpConfig jumpConfig = new JumpConfig(jumpHostList, master);
        List<PortMappingEntity> mappingConfig = data.getMappingModel().stream().map(item -> new PortMappingEntity(item.getLocal(), item.getlPort(), item.getRemote(), item.getrPort())).collect(Collectors.toList());
        JumpMappingConfig config = new JumpMappingConfig(jumpConfig, mappingConfig);
        return config;
    }
}
